package cc.rengu.igas.opms.core.service.trans.common;

import cc.rengu.igas.momp.facade.bean.PrePaymentAvailableCouponMcInfoBean;
import cc.rengu.igas.momp.facade.bean.PrePaymentAvailableMoneyOffMcInfoBean;
import cc.rengu.igas.momp.facade.bean.UserMcInfoBean;
import cc.rengu.igas.momp.facade.response.OpmsQueryAvailableDiscountInfoBeforePaymentResponse;
import cc.rengu.igas.momp.facade.response.QueryAvailableDiscountInfoBeforePaymentResponse;
import cc.rengu.igas.momp.facade.result.Result;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.bean.DiscountInfo;
import cc.rengu.igas.opms.facade.bean.MoneyOffInfo;
import cc.rengu.igas.opms.facade.request.UserCouponListRequest;
import cc.rengu.igas.opms.facade.response.UserCouponListResponse;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.constant.UserSessionConstant;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.CheckResultEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户优惠券列表查询
 * 根据是否存在用户订单选择不同的处理方法
 * 不存在用户订单时(静态码扫码支付),直接向营销系统发起查询，校验优惠劵金额大于交易金额的优惠劵不可用
 * 存在用户订单时，组orderDetail信息查询。校验商户订单中必须有交易金额大于优惠劵金额此优惠劵金额方可使用
 *
 * @author keyi
 * @modify by wangcheng
 * @date 2020/4/26.
 */
public class UserCouponListService extends ManageService implements TransCustomImpl {
    @Override
    protected Object bizBeforeCust() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        UserCouponListRequest userCouponListRequest = new UserCouponListRequest();
        ConvertUtil.convertOutput(userCouponListRequest);
        if ("1".equals(userCouponListRequest.getUserType()) || "2".equals(userCouponListRequest.getUserType())) {
            /* 微信支付宝扫码特殊处理，先解密userId然后再Base64解码*/
            if (!StringUtil.isEmptyOrNull(userCouponListRequest.getUserId())) {
                UserService userService = new UserServiceImpl();
                String sensitiveKey = userService.getUserSessionValue(UserSessionConstant.SENSITIVE_KEY);
                if (StringUtil.isEmptyOrNull(sensitiveKey)) {
                    rglog.info("用户会话敏感信息密钥不存在,不对微信或支付宝用户标识进行解密处理!");
                    return userCouponListRequest;
                }
                String decryUserId = AESUtil.pkcs7CbcDecryptData(Base64.decodeBase64(sensitiveKey), Base64.decodeBase64(userCouponListRequest.getUserId()));
                rglog.debug("微信支付宝解密后的userId:<{}>", decryUserId);
                String userId = new String(Base64.decodeBase64(decryUserId.getBytes(StandardCharsets.UTF_8)));
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.USER_ID, userId);
                userCouponListRequest.setUserId(userId);
            }
        }
        return userCouponListRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        UserCouponListRequest userCouponListRequest = (UserCouponListRequest) request;
        String instId = userCouponListRequest.getHeader().getInstId();
        String userOrderId = userCouponListRequest.getUserOrderId();
        String orderAmt = AmountUtil.checkAmt(userCouponListRequest.getOrderAmt(), 2);
        userCouponListRequest.setOrderAmt(orderAmt);

        //存在用户订单的时候校验商户订单
        UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
        UserOrderInfo userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByUserOrderId(instId, userOrderId);
        if (null != userOrderInfo) {
            if (!StringUtil.isEmptyOrNull(userOrderInfo.getDiscountInfo())) {
                rglog.info("用户已经使用了优惠劵，userDiscountInfo:<{}>", userOrderInfo.getDiscountInfo());
                return new BizResponse(OpmsParamConstant.OPM_SYS_ID, RespCodeEnum.TRANS_SUCCESS.getRespCode(), RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.USER_ORDER_INFO, userOrderInfo);
            //获取商户订单
            MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
            List<MchntOrderInfo> mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(instId, userOrderInfo.getSysSeqNum());
            //若是购买卡券的订单不再查询营销信息，返回空
            if (null != mchntOrderInfoList && ("00".equals(mchntOrderInfoList.get(0).getBizSceneType()) || "02".equals(mchntOrderInfoList.get(0).getBizSceneType()))) {
                rglog.info("购买卡券的交易:<{}>不查询用户可用的优惠券信息,返回空", mchntOrderInfoList.get(0).getBizSceneType());
                return new BizResponse(OpmsParamConstant.OPM_SYS_ID, RespCodeEnum.TRANS_SUCCESS.getRespCode(), RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);
            //校验订单支付金额，有金额的校验金额，无金额的设置交易金额
            if (!StringUtil.isEmptyOrNull(userOrderInfo.getOrderExtraInfo())) {
                JSONObject orderExtraInfo = JSON.parseObject(userOrderInfo.getOrderExtraInfo());
                //金额来源
                String amtSource = orderExtraInfo.getString(OpmsParamConstant.ORDER_AMT_SOURCE);
                rglog.info("订单交易金额来源 amtSource:<{}>", amtSource);
                //校验或者更新金额
                if ("00".equals(amtSource)) {
                    //固定支付金额，校验订单的支付金额和请求的交易金额是否一致
                    if (AmountUtil.compare(orderAmt, userOrderInfo.getOrderAmt()) != 0) {
                        //有金额的校验金额
                        rglog.error("交易金额不一致，orderAmt:<{}>, txnAmt:<{}>", userOrderInfo.getOrderAmt(), orderAmt);
                        throw new BizException(RespCodeEnum.TRANS_AMT_DISACCORD.getRespCode(), RespCodeEnum.TRANS_AMT_DISACCORD.getRespDesc());
                    }
                } else {
                    //动态支付金额，在支付金额为空的时候更新支付金额
                    rglog.info("更新用户订单金额");
                    if (StringUtil.isEmptyOrNull(userOrderInfo.getOrderAmt()) || AmountUtil.compare(userOrderInfo.getOrderAmt(), "0") <= 0) {
                        userOrderInfo.setOrderCcy("156");
                        userOrderInfo.setOrderAmt(orderAmt);
                        userOrderInfo.setNeedPayAmt(orderAmt);
                    }
                    if (mchntOrderInfoList != null) {
                        for (MchntOrderInfo mchDto : mchntOrderInfoList) {
                            if (StringUtil.isEmptyOrNull(mchDto.getOrderAmt()) || AmountUtil.compare(mchDto.getOrderAmt(), "0") <= 0) {
                                mchDto.setOrderAmt(orderAmt);
                                mchDto.setRealSettleAmt(orderAmt);
                            }
                        }
                    }
                }
            }
        }

        //调用营销接口查询
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(userCouponListRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, null, channelCallCfg.getBizScene(), request);

        //组装应答
        UserCouponListResponse userCouponListResponse = new UserCouponListResponse();
        List<DiscountInfo> discountInfoList = (List<DiscountInfo>) GlobalTransUtil.getCacheValue(TransCacheConstant.DISCOUNT_INFO_LIST);
        userCouponListResponse.setDiscountInfoList(discountInfoList);
        List<MoneyOffInfo> moneyOffInfoList = (List<MoneyOffInfo>) GlobalTransUtil.getCacheValue(TransCacheConstant.MONEY_OFF_INFO_LIST);
        userCouponListResponse.setMoneyOffInfoList(moneyOffInfoList);
        BizResponse<UserCouponListResponse> bizResponse = new BizResponse<>();
        bizResponse.setResult(userCouponListResponse);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UserCouponListResponse userCouponListResponse = (UserCouponListResponse) bizResponse.getResult();
        ConvertUtil.convertInput(userCouponListResponse);
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        UserCouponListRequest userCouponListRequest = (UserCouponListRequest) request;
        //业务场景代码：00-收银台页面直接支付场景，01-收银台页面跳转到手机银行APP上再选卡支付场景
        String bizScene = StringUtil.isEmptyOrNull(userCouponListRequest.getAcctNo()) ? "00" : "01";
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals(bizScene)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        UserCouponListRequest userCouponListRequest = (UserCouponListRequest) request;
        rglog.info("根据用户类型获取调用营销的userId值:<{}>", userCouponListRequest.getUserType());
        if ("1".equals(userCouponListRequest.getUserType()) || "2".equals(userCouponListRequest.getUserType())) {
            //业务场景代码：00-收银台页面直接支付场景，01-收银台页面跳转到手机银行APP上再选卡支付场景
            if ("00".equals(channelCallCfg.getBizScene())) {
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_USER_INFO, userCouponListRequest.getUserId());
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_USER_TYPE, "1".equals(userCouponListRequest.getUserType()) ? "2" : "3");
            } else {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("phoneNo", "");
                jsonObject.put("cardNo", userCouponListRequest.getAcctNo());
                jsonObject.put("coreComId", "");
                jsonObject.put("wechatId", "1".equals(userCouponListRequest.getUserType()) ? userCouponListRequest.getUserId() : "");
                jsonObject.put("alipayId", "2".equals(userCouponListRequest.getUserType()) ? userCouponListRequest.getUserId() : "");
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_USER_INFO, jsonObject.toJSONString());
            }
        } else {
            //检查用户是否存在
            UserService userService = new UserServiceImpl();
            UserInfo userInfo = userService.getUserInfo(userCouponListRequest.getHeader().getInstId(), userCouponListRequest.getUserId(), userCouponListRequest.getHeader().getSession());
            if (null == userInfo) {
                rglog.error("获取用户信息失败!");
                throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
            }
            //业务场景代码：00-收银台页面直接支付场景，01-收银台页面跳转到手机银行APP上再选卡支付场景
            if ("00".equals(channelCallCfg.getBizScene())) {
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_USER_INFO, userInfo.getUserId());
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_USER_TYPE, "0");
            } else {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("phoneNo", userInfo.getMobileNo());
                jsonObject.put("cardNo", userCouponListRequest.getAcctNo());
                jsonObject.put("coreComId", userInfo.getUserApexMap().get(UserSessionConstant.CORE_CUSTOMER_ID));
                jsonObject.put("wechatId", "");
                jsonObject.put("alipayId", "");
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_USER_INFO, jsonObject.toJSONString());
            }
        }
        //手机银行APP支付场景将营销活动编号、规则编号及订单优惠金额放到交易缓存中
        if ("01".equals(channelCallCfg.getBizScene())) {
            GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_MC_NO, userCouponListRequest.getMcNo());
            GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_RULE_INDEX, userCouponListRequest.getRuleIndex());
            GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_DISCOUNT_AMT, userCouponListRequest.getDiscountAmt());
        }
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        UserCouponListRequest userCouponListRequest = (UserCouponListRequest) request;
        List<UserMcInfoBean> userMcInfoBeanList = null;
        //业务场景代码：00-收银台页面直接支付场景，01-收银台页面跳转到手机银行APP上再选卡支付场景
        if ("00".equals(channelCallCfg.getBizScene())) {
            Result<QueryAvailableDiscountInfoBeforePaymentResponse> callResult = (Result<QueryAvailableDiscountInfoBeforePaymentResponse>) channelResponse;
            if (null != callResult && null != callResult.getResult()) {
                userMcInfoBeanList = callResult.getResult().getUserMcInfoBeanList();
            }
        } else {
            Result<OpmsQueryAvailableDiscountInfoBeforePaymentResponse> callResult = (Result<OpmsQueryAvailableDiscountInfoBeforePaymentResponse>) channelResponse;
            if (null != callResult && null != callResult.getResult()) {
                userMcInfoBeanList = callResult.getResult().getUserMcInfoBeanList();
            }
        }
        if (null != userMcInfoBeanList) {
            List<PrePaymentAvailableCouponMcInfoBean> couponInfoList = new ArrayList<>();
            userMcInfoBeanList.forEach(item -> {
                if (null != item.getCouponInfoList()) {
                    couponInfoList.addAll(item.getCouponInfoList());
                }
            });
            List<PrePaymentAvailableMoneyOffMcInfoBean> moneyOffInfoList = new ArrayList<>();
            userMcInfoBeanList.forEach(item -> {
                if (null != item.getMoneyOffInfoList()) {
                    moneyOffInfoList.addAll(item.getMoneyOffInfoList());
                }
            });
            //优惠劵列表信息
            List<DiscountInfo> discountInfoList = new ArrayList<>();
            for (PrePaymentAvailableCouponMcInfoBean bean : couponInfoList) {
                DiscountInfo discountInfo = new DiscountInfo();
                discountInfo.setDiscountId(bean.getCouponNo());
                discountInfo.setDiscountDesc(bean.getRuleContent());
                discountInfo.setCriteria("");
                discountInfo.setDiscountAmt(bean.getCouponAmt());
                discountInfo.setExprDate(bean.getCouponEndDate());
                //商户订单金额是否大于卡劵优惠金额
                boolean amtOverOrderAmt = false;
                boolean couponStatus = OpmsParamConstant.STR_ONE.equals(bean.getCouponStatus());
                UserOrderInfo userOrderInfo = (UserOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.USER_ORDER_INFO);
                if (null != userOrderInfo) {
                    List<MchntOrderInfo> mchntOrderInfoList = (List<MchntOrderInfo>) GlobalTransUtil.getCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST);
                    for (MchntOrderInfo mchntOrderInfo : Objects.requireNonNull(mchntOrderInfoList)) {
                        if (AmountUtil.compare(mchntOrderInfo.getOrderAmt(), bean.getCouponAmt()) == 1) {
                            amtOverOrderAmt = true;
                            break;
                        }
                    }
                    if (amtOverOrderAmt && couponStatus) {
                        discountInfo.setCouponStatus(OpmsParamConstant.STR_ONE);
                    } else {
                        discountInfo.setCouponStatus(OpmsParamConstant.STR_ZERO);
                    }
                } else {
                    if (AmountUtil.compare(userCouponListRequest.getOrderAmt(), bean.getCouponAmt()) == 1) {
                        discountInfo.setCouponStatus(OpmsParamConstant.STR_ONE);
                    } else {
                        discountInfo.setCouponStatus(OpmsParamConstant.STR_ZERO);
                    }
                }
                discountInfoList.add(discountInfo);
                GlobalTransUtil.setCacheValue(TransCacheConstant.DISCOUNT_INFO_LIST, discountInfoList);
            }

            //减免类优惠信息
            List<MoneyOffInfo> moneyOffInfos = new ArrayList<>();
            for (PrePaymentAvailableMoneyOffMcInfoBean bean : moneyOffInfoList) {
                MoneyOffInfo moneyOffInfo = new MoneyOffInfo();
                moneyOffInfo.setMcNo(bean.getMcNo());
                moneyOffInfo.setMcType(bean.getMcType());
                moneyOffInfo.setMcStartDate(bean.getMcStartDate());
                moneyOffInfo.setMcEndDate(bean.getMcEndDate());
                moneyOffInfo.setRuleContent(bean.getRuleContent());
                moneyOffInfos.add(moneyOffInfo);
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.MONEY_OFF_INFO_LIST, moneyOffInfos);
        }
        return transStatusEnum;
    }
}
